using Basis;
using NL;
using NL.AdreesableAsset;
using NL.Advanced;
using NL.Combat;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Miya.EmisssionLauncher
{

    public interface ILaunchPrepare
    {
        IEnumerator Prepare();
    }
    public interface ILaunchPreAction
    {
        IEnumerator PreAction();
    }
    public interface ILaunchingLoop
    {
        void OnLoopBegin();
        void OnLoopEnd();

        void OnLoopOneBegin();
        void OnLoopOneEnd();
        void OnLoopOneBB(GameObject bb);

    }

    public class Launcher : Passivity
    {



        [Header("整个引导得时长")]
        public float Life = 0;

        [Header("攻击间隔;攻击距离;目标数量")]
        public float coc = 1f;
        public virtual float COC => coc;



        [Header("目标数量. =0 不需要目标.")]
        public int TargetCount=0;
        public virtual int  TARGET_COUNT => TargetCount;

        public float TargetDuration = 0;
        public bool ForceTarget = false;



        [Header("子弹,分几波次,间隔")]
        public GameObject Mod_Bullet;
        public int Count = 1;
        public float Duration = 0.1f;
        public virtual int COUNT => Count;
        public virtual float DURATION => Duration;

        [Header("发射循环几次.")]
        public int LoopCount = 1;
        public float LoopDuration = 0.1f;
        public virtual int LOOP_COUNT => LoopCount;
        public float LOOP_DURATION => LoopDuration;
        [Header("发射后是否销毁")]
        public bool LaunchDestroy = false;
        [Header("是否暂停发射")]
        public bool LaunchPause = false;
        [Header("----RUNTIME-----")]
        public CastingState State = CastingState.None;

        public bool Runing => State == CastingState.Action || State == CastingState.PreAction || State == CastingState.Prepare;




        //上一次 释放时间...  是否可以释放周期==CD冷却
        protected float _LastLaunchTime = -100f;
        public float LaunchPassed => Time.time - _LastLaunchTime;
        public bool COCReady => LaunchPassed > COC;
        public bool ColdReady => COCReady;



        public  ICombatOwner TargetTop=> TargetsNow!=null&& TargetsNow.Count>0? TargetsNow[0]:null;
        public virtual bool TargetReady
        {
            get
            {
                _CheckTarget();
                return TargetTop != null;
            }
        }


        // 释放可否 判断...
        public virtual bool CanCast
        {
            get
            {
                //检查 释放周期
                if (!COCReady) return false;

                //检查目标合规.
                if(TARGET_COUNT > 0 &&  !TargetReady) return false;

                return true;
            }
            
        } 




        //发射的目标位置  默认在自己前方1得位置.
        public virtual Vector3 LaunchPos => transform.position + transform.forward;

        //发射的方向  默认自己得前方向.
        public Vector3 LaunchForward => transform.forward;

        protected virtual Transform GetLunchRoot(Transform target) => transform;






        protected Emission[] Emissions;

        protected ILaunchPrepare _LaunchPrepare;
        protected ILaunchPreAction _LaunchPreAction;
        protected ILaunchingLoop[] _LaunchingLoops;
        protected Property _Property;

        /// 生命周期................................................
        /// 生命周期................................................ 
        /// 生命周期................................................


        protected override void Awake()
        {
            base.Awake();


            Emissions = GetComponentsInChildren<Emission>();

            _LaunchPrepare = GetComponent<ILaunchPrepare>();
            _LaunchPreAction = GetComponent<ILaunchPreAction>();
            _LaunchingLoops = GetComponents<ILaunchingLoop>();

        }

        protected override void OnLive()
        {
            base.OnLive(); 
            
            State = CastingState.None;
        }

        /// <summary>
        /// 加载数据源....
        /// </summary>
        protected override  void _LoadInfo()
        {
            base._LoadInfo();
            if (Info == null) return;

            string str = "";

            //下面是 根据数据源.重置相关 参数.
            ID = Info["id"].AsInt;

            coc = Info["coc"].AsFloatDefault(coc);

            Count = Info["count"].AsIntDefault(Count);

            Duration = Info["duration"].AsFloatDefault(Duration);






            //读取子弹
            str = Info["bb"].AsString;
            if (!string.IsNullOrEmpty(str))
            {
                Mod_Bullet = AA.LoadAndWait(str);
            }




        }


        public List<ICombatOwner> TargetsAll => _TargetCollecterOwner!=null? _TargetCollecterOwner.All:new List<ICombatOwner>();

        //检查目标..
        public  List<ICombatOwner> TargetsNow=new List<ICombatOwner>();

        ITargetCollecter _TargetCollecterOwner;
        void  _CheckTarget()
        {
            _TargetCollecterOwner = _TargetCollecterOwner ?? GetComponentInParent<ITargetCollecter>();

            TargetsNow=_TargetCollecterOwner.GetTop(TARGET_COUNT);
        }
        /////
        ///  发射流程
        ///  1.....发射前校验 是否可以发射?
        ///  2.....发射准备 --二次校验 
        ///  3.....发射前摇 --三次校验
        ///  4.....发射开始---
        ///  5.....循环波次.. 
        ///  6.....发射结束.. 
        ///  7.....发射后摇---重置所有...
        /// 公开方法................................................
        /// 公开方法................................................ 
        /// 公开方法................................................   
        public Launcher Launch()
        {
            if (!gameObject.activeInHierarchy) return this;
            if (LaunchPause) return this;
            _Launch();

            return this;
        }
        protected void _Launch()
        {
            if (State == CastingState.Prepare || State == CastingState.PreAction)
            {
                //LOG.Add($"[LauncherBase._Launch]::{name},{GetInstanceID()}====CantLaunch@{State}");
                return;
            }


            if (!CanCast)
            {
                //Debug.LogWarning($"[Launcher._Launch]:_CanLaunch false {_LastLaunchTime},{COC}");
                return;
            }

            // 可是发射了.....................................
            PrepareLaunch();
            StartCoroutine(_LaunchRuner());
        }

        protected virtual void PrepareLaunch()
        {

        }

        /// <summary>
        /// 核心..释放逻辑 
        /// Prepare---->_PreLaunch---->
        /// </summary>
        /// <returns></returns>
        IEnumerator _LaunchRuner()
        {
            if(CombatSetting.LOGable)
                LOG.Add($"[Launcher._LaunchRuner]:{name},{GetInstanceID()}.........................BEGIN,{Time.time}");

            // 开展发射准备........
            State = CastingState.Prepare;
            yield return _Prepare();

            // 二次检查 是否可以 发射..
            if (!CanCast)
            {
                Stop("!CanCasting <<_Prepare");
                yield break;
            }


            // 开展发射前摇..........
            State = CastingState.PreAction;
            yield return _PreAction();

            // 三次次检查 是否可以 发射..
            if (!CanCast)
            {
                Stop("!CanCasting <<_PreLaunch");
                yield break;
            }


            //  可以正式发射了.......................

            State = CastingState.Action;
            _LastLaunchTime = Time.time;
            if (CombatSetting.LOGable) 
                LOG.Add($"[Launcher._LaunchRuner]:{name},{GetInstanceID()},{State}.........................{Time.time}");


            //开始
            _DoLaunchBegin();


            for(int i=0;i< LOOP_COUNT; i++)
            {
                // 开始一个释放周期...
                StartCoroutine(_LaunchLooper());

                yield return new WaitForSeconds(LOOP_DURATION);
            }






            //结束
            _DoLaunchEnd();




            State = CastingState.Ending;


            State = CastingState.None;
            if (CombatSetting.LOGable) 
                LOG.Add($"[Launcher._LaunchRuner]:{name},{GetInstanceID()}........................END,{Time.time}");

            if(LaunchDestroy)
            {
                if (CombatSetting.LOGable) 
                    LOG.Add($"[Launcher._LaunchRuner]:{name},{GetInstanceID()}........................DESTROY,{Time.time}");
                yield return 0;
                //this.SETActive(false);
                Destroy(gameObject);
            }
        }


        IEnumerator _Prepare()
        {

            if (_LaunchPrepare != null)
                yield return _LaunchPrepare.Prepare();
        }
        IEnumerator _PreAction()
        {
            if (_LaunchPreAction != null)
                yield return _LaunchPreAction.PreAction();
        }
        protected void _DoLaunchBegin()
        {

            OnLaunchBegin();
            _ONLaunchBegin?.Invoke(this);
        }
        protected virtual void OnLaunchBegin()
        {

        }

        Action<Launcher> _ONLaunchBegin;
        public Launcher WaitLaunchBegin(Action<Launcher> on)
        {
            _ONLaunchBegin = on; return this;
        }



        protected virtual IEnumerator _LaunchLooper()
        {
            if (CombatSetting.LOGable) 
                LOG.Add($"[Launcher._LaunchLooper]:{name},{GetInstanceID()}........BEGIN,{Time.time}");

            foreach (var ll in _LaunchingLoops) ll.OnLoopBegin();

            //循环每轮发射的波次
            var num = COUNT;// FixCount();

            for (int i = 0; i < num; i++)
            {
                //处理多重目标

                if (TARGET_COUNT < 1)
                {

                    StartCoroutine(_DoLuanchLoopOne());
                }else
                {
                    StartCoroutine(_launchLoopTarget());
                }


                yield return new WaitForSeconds(DURATION);

            }

            foreach (var ll in _LaunchingLoops) ll.OnLoopEnd();

            if (CombatSetting.LOGable) 
                LOG.Add($"[Launcher._LaunchLooper]:{name},{GetInstanceID()}........END,{Time.time}");
        }

        protected virtual IEnumerator _launchLoopTarget()
        {
            int itor = Math.Min(TargetsNow.Count, TARGET_COUNT);
            if (ForceTarget) itor = TARGET_COUNT;
            for (int t = 0; t < itor; t++)
            {
                var target = TargetsNow[t % TargetsNow.Count];
                if (target != null)
                {
                    StartCoroutine(_DoLuanchLoopOne(target.transform));
                }

                if (TargetDuration > 0) yield return new WaitForSeconds(TargetDuration);
            }
        }

        //处理每轮发射的波次
        protected virtual IEnumerator _DoLuanchLoopOne(Transform target=null)
        {
            if (CombatSetting.LOGable)
                LOG.Add($"[Launcher._DoLuanchLoopOne]:{name},{GetInstanceID()}........BEGIN,{Time.time}");
            //处理发射点
            Transform _lauchroot = GetLunchRoot(target);

            if (_lauchroot == null)
            {
                if (CombatSetting.LOGable) 
                    Debug.LogError($"[Launcher._DoLuanchOne]:error: LunchRoot=null");
                yield break;
            }


            //transform.SETAs(_lauchroot);
            OnLaunchLoopOneBegin();
            foreach (var ll in _LaunchingLoops) ll.OnLoopOneBegin();


            var _emissons = _GetEmissions();
            //检查发射阵列
            if (_emissons != null)
            {
                foreach (var data in _emissons)
                {

                    Vector3 pos = _lauchroot.TransformPoint(data.Position);
                    Vector3 dir = _lauchroot.TransformDirection(data.Direction);
                    _DoLaunchOneBB(pos, dir, target!=null?target.gameObject:null);
                    
                    //// 不需要目标 直接发射..
                    //if (TargetCount < 1)
                    //{
                    //    _DoLaunchOneBB(pos, dir, null);
                    //}else
                    //{//需要目标...
                    //    if (NowTargets.Count > 0)
                    //    {
                    //        var top = NowTargets[0];
                    //        foreach (var a in NowTargets)
                    //        {
                    //            Vector3 thisdir = dir;
                    //            if (a != top)
                    //            {
                    //                //对过对象方向差计算发射方向.
                    //                Quaternion Q = Quaternion.FromToRotation((top.transform.position - transform.position).normalized, (a.transform.position - transform.position).normalized);
                    //                thisdir = Q*thisdir;
                    //            }

                    //            _DoLaunchOneBB(pos, thisdir, a.gameObject);
                    //        }
                    //    }


                    //}

                    ///  处理 多重目标得发射
       



                    if (data.Duration > 0)
                        yield return new WaitForSeconds(data.Duration);
                }
            }

            if (_lauchroot != null && _lauchroot.name.Equals("#"))
            {
                Destroy(_lauchroot.gameObject);
            }


            foreach (var ll in _LaunchingLoops) ll.OnLoopOneEnd();
            OnLaunchLoopOneEnd();
            if (CombatSetting.LOGable) 
                LOG.Add($"[Launcher._DoLuanchLoopOne]:{name},{GetInstanceID()}........END,{Time.time}");
        }
        protected virtual void OnLaunchLoopOneBegin()
        {

        }
        protected virtual void OnLaunchLoopOneEnd()
        {

        }
        protected void _DoLaunchOneBB(Vector3 from, Vector3 dir, GameObject target)
        {

            if (Mod_Bullet == null)
                return;

           
            
            var one = BPoolMan.POOL["BB"].Create(Mod_Bullet);
            one.transform.position = from;
            one.transform.forward = dir;

            GameObject _LauncherOwner = gameObject;
            if(ParentLauncherOwner != null)
            {
                _LauncherOwner = ParentLauncherOwner.gameObject;
            }
            one.GetComponent<BB>()?.SetCombatOwner(CombatOwner, 1).SetLauncherOwner(_LauncherOwner);





            // 处理 BB目标
            //GameObject target = TargetTop==null?null: TargetTop.gameObject;
            if (target != null)
            {
                var all = one.GetComponents<ITargetable>();
                if(all != null)
                {
                    foreach (var a in all)
                        a.SetTarget(target);
                }
            }

            //处理忽略目标
            var ignor = GetComponent<ITargetIgnor>();
            if (ignor != null )
            {
                one.IGNORAdd(ignor.IgnorAll);
            }


            //呼叫 发射循环附件...
            foreach (var ll in _LaunchingLoops)
            {
                ll.OnLoopOneBB(one);
            }

            OnLoopOneBB(one);
        }


    

        protected virtual void OnLoopOneBB(GameObject bb)
        {

        }

        public bool LoadEmissionOnPlaying = false;
        protected virtual IEnumerable<EmissionData> _GetEmissions()
        {
            if (LoadEmissionOnPlaying)
            {
                Emissions = GetComponentsInChildren<Emission>();
            }
            if (Emissions == null || Emissions.Length == 0)
                return new EmissionData[1] { EmissionData.Identy };

            List<EmissionData> _data = new List<EmissionData>();

            if (Emissions != null && Emissions.Length > 0)
            {
                foreach (var emm in Emissions)
                {
                    if (!emm.enabled) continue;
                    _data.AddRange(emm.GetEmissions());
                }

            }
            return _data;


        }

        protected virtual void _DoLaunchEnd()
        {
            OnLaunchEnd();
            _ONLaunchEnd?.Invoke(this);
        }

        protected virtual void OnLaunchEnd()
        {

        }

        Action<Launcher> _ONLaunchEnd;
        public Launcher WaitLaunchEnd(Action<Launcher> on)
        {
            _ONLaunchEnd = on; return this;
        }


        public void Stop(string code = "")
        {

            _DoStop();
        }
        protected virtual void _DoStop(string code = "")
        {
            _Cancel();
            if (CombatSetting.LOGable) 
                LOG.Add($"[Launch.Stop({code})]............");
        }
        public Launcher Pause()
        {

            _DoPause(); return this;
        }
        protected virtual void _DoPause()
        {


        }
        protected void _Cancel()
        {

            StopAllCoroutines();
            State = CastingState.None;
        }

        public Launcher Resume()
        {

            _DoResume(); return this;
        }
        protected virtual void _DoResume()
        {
        }

        protected override void OnDisable()
        {
            _LastLaunchTime = 0;
            base.OnDisable();
        }
    }
}

